#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <stdlib.h>
#include <iostream>
#include <map>
#include <string.h>
#include <stdarg.h>


// ODBC includes
#include <sql.h>
#include <sqlext.h>

// libodbclogger includes
#include "DynLib.h"
#include "ODBCWrapper.h"

using namespace std;

#define ODBC_DRIVER_ENV_VAR_NAME "ODBC_DRIVER"
#define LOG_PREFIX "[ODBC Logging Driver] "

/**
 * NASTY GLOBAL VARIABLE
 */
static ODBCWrapper *_logging_odbc_driver_wrapper = NULL;

ODBCWrapper *getWrapper() {

    if (_logging_odbc_driver_wrapper==NULL) {

        char *driverPath = getenv(ODBC_DRIVER_ENV_VAR_NAME);
        if (driverPath==NULL) {
            cerr << LOG_PREFIX << "Environment variable " << ODBC_DRIVER_ENV_VAR_NAME << " is not defined" << endl;
            return NULL;
        }

        _logging_odbc_driver_wrapper = new ODBCWrapper(driverPath);
        if (!_logging_odbc_driver_wrapper->init()) {
            cerr << LOG_PREFIX << "Failed to initialize library " << driverPath << endl;
            delete _logging_odbc_driver_wrapper;
            _logging_odbc_driver_wrapper = NULL;
            return NULL;
        }
    }

    return _logging_odbc_driver_wrapper;
}

char* formatSQLCHAR(SQLCHAR* string) {
    if (string==NULL) {
        char *temp = (char *) new char[1];
        temp[0] = '\0';
        return temp;
    }
    int len = strlen((char*)string);
    char *temp = (char *) new char[len+1];
    sprintf(temp, "%s", (char*)string);
    return temp;
}

char* formatPointer(void *p) {
    char *temp = (char *) new char[32];
    sprintf(temp, "%p", p);
    return temp;
}

char* formatSQLHENV(void *p) {
    return formatPointer(p);
}

char* formatSQLHDBC(void *p) {
    return formatPointer(p);
}

char* formatSQLHSTMT(void *p) {
    return formatPointer(p);
}

char* formatSQLHDESC(void *p) {
    return formatPointer(p);
}

char* formatSQLHWND(void *p) {
    return formatPointer(p);
}

char* formatSQLHANDLE(void *p) {
    return formatPointer(p);
}

char* formatSQLPOINTER(void *p) {
    return formatPointer(p);
}

char* formatSQLLEN(SQLLEN l) {
    char *temp = (char *) new char[32];
#if (SIZEOF_LONG == 8)
    sprintf(temp, "%d", l);
#else
    sprintf(temp, "%ld", l);
#endif
    return temp;
}

char* formatSQLULEN(SQLULEN l) {
    char *temp = (char *) new char[32];
#if (SIZEOF_LONG == 8)
    sprintf(temp, "%d", l);
#else
    sprintf(temp, "%ld", l);
#endif
    return temp;
}

char* formatSQLINTEGER(SQLINTEGER l) {
    char *temp = (char *) new char[32];
    sprintf(temp, "%d", l);
    return temp;
}

char* formatSQLSMALLINT(SQLSMALLINT l) {
    char *temp = (char *) new char[32];
    sprintf(temp, "%d", l);
    return temp;
}

char* formatSQLUSMALLINT(SQLUSMALLINT l) {
    char *temp = (char *) new char[32];
    sprintf(temp, "%d", l);
    return temp;
}

void log_odbc_call(string functionName, SQLRETURN ret, struct timeval *tvStart, struct timeval *tvEnd, int numArgs, ...) {

    // output format should be something like this
    // [ODBC Logging Driver][SQL_SUCCESS][1.012345][SQLExecDirect][StatementHandle][0x1234567][SQL][SELECT * FROM foo]


    // return code
	const char *returnCode = "UNKNOWN";
	switch (ret) {
		case SQL_SUCCESS:
			returnCode = "SQL_SUCCESS";
			break;
		case SQL_SUCCESS_WITH_INFO:
			returnCode = "SQL_SUCCESS_WITH_INFO";
			break;
		case SQL_ERROR:
			returnCode = "SQL_ERROR";
			break;
		case SQL_NO_DATA:
			returnCode = "SQL_NO_DATA";
			break;
		case SQL_INVALID_HANDLE:
			returnCode = "SQL_INVALID_HANDLE";
			break;
		case SQL_STILL_EXECUTING:
			returnCode = "SQL_STILL_EXECUTING";
			break;
	}

    // calculate elapsed time in seconds
    struct timeval tvDiff;
	timersub(tvEnd, tvStart, &tvDiff);
	char temp[64]; //TODO: is this definitely large enough?
	sprintf(temp, "%ld.%06ld", tvDiff.tv_sec, tvDiff.tv_usec);

    string outputLine = string("[") + string(returnCode)
        + string("][") + string(temp)
        + string("][") + functionName
        + string("][") + formatSQLINTEGER((SQLINTEGER)numArgs)
        + string("]");

    //TODO: write code to read varargs and add to output line - see this web page to get started

    // http://www.eskimo.com/~scs/cclass/int/sx11b.html

    va_list argp;
    va_start(argp, numArgs);

    for (int i=1; i<=numArgs; i++) {

        //cerr << functionName << " arg " << i << " of " << numArgs << endl;

        char *argType = va_arg(argp, char*);
        //cerr << "argType " << argType << endl;

        char *argName = va_arg(argp, char*);
        //cerr << "argName " << argName << endl;

        char *argValue = va_arg(argp, char*);
        //cerr << "argValue " << argValue << endl;

        outputLine += string("[") + string(argType)
                    + string("][") + string(argName)
                    + string("][") + argValue
                    + string("]");

    }

    va_end(argp);

    // output the logging line
    cerr << LOG_PREFIX << outputLine << endl;
}


SQLRETURN notImplemented(const char *functionName) {
    // log detailed error information
	cerr << LOG_PREFIX << string("Call to unimplemented function: ") + string(functionName) << endl;
	// return error code
	return SQL_ERROR;
}


// CODE GENERATED ...


SQLRETURN SQL_API SQLAllocConnect(SQLHENV EnvironmentHandle, SQLHDBC* ConnectionHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLAllocConnect(EnvironmentHandle, ConnectionHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHENV(EnvironmentHandle);
	char* arg2 = formatPointer((void*)ConnectionHandle);
	log_odbc_call("SQLAllocConnect", ret, &tvStart, &tvEnd, 2, "SQLHENV", "EnvironmentHandle", arg1, "SQLHDBC*", "ConnectionHandle", arg2);
	delete [] arg1;
	delete [] arg2;
	return ret;
}

SQLRETURN SQL_API SQLAllocEnv(SQLHENV* EnvironmentHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLAllocEnv(EnvironmentHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatPointer((void*)EnvironmentHandle);
	log_odbc_call("SQLAllocEnv", ret, &tvStart, &tvEnd, 1, "SQLHENV*", "EnvironmentHandle", arg1);
	delete [] arg1;
	return ret;
}

SQLRETURN SQL_API SQLAllocStmt(SQLHDBC ConnectionHandle, SQLHSTMT* StatementHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLAllocStmt(ConnectionHandle, StatementHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDBC(ConnectionHandle);
	char* arg2 = formatPointer((void*)StatementHandle);
	log_odbc_call("SQLAllocStmt", ret, &tvStart, &tvEnd, 2, "SQLHDBC", "ConnectionHandle", arg1, "SQLHSTMT*", "StatementHandle", arg2);
	delete [] arg1;
	delete [] arg2;
	return ret;
}

SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT HandleType, SQLHANDLE InputHandle, SQLHANDLE* OutputHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLAllocHandle(HandleType, InputHandle, OutputHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLSMALLINT(HandleType);
	char* arg2 = formatSQLHANDLE(InputHandle);
	char* arg3 = formatPointer((void*)OutputHandle);
	log_odbc_call("SQLAllocHandle", ret, &tvStart, &tvEnd, 3, "SQLSMALLINT", "HandleType", arg1, "SQLHANDLE", "InputHandle", arg2, "SQLHANDLE*", "OutputHandle", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLBindCol(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValue, SQLLEN BufferLength, SQLLEN* StrLen_or_Ind)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLBindCol(StatementHandle, ColumnNumber, TargetType, TargetValue, BufferLength, StrLen_or_Ind);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLUSMALLINT(ColumnNumber);
	char* arg3 = formatSQLSMALLINT(TargetType);
	char* arg4 = formatSQLPOINTER(TargetValue);
	char* arg5 = formatSQLLEN(BufferLength);
	char* arg6 = formatPointer((void*)StrLen_or_Ind);
	log_odbc_call("SQLBindCol", ret, &tvStart, &tvEnd, 6, "SQLHSTMT", "StatementHandle", arg1, "SQLUSMALLINT", "ColumnNumber", arg2, "SQLSMALLINT", "TargetType", arg3, "SQLPOINTER", "TargetValue", arg4, "SQLLEN", "BufferLength", arg5, "SQLLEN*", "StrLen_or_Ind", arg6);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	return ret;
}

SQLRETURN SQL_API SQLBindParam(SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNumber, SQLSMALLINT ValueType, SQLSMALLINT ParameterType, SQLULEN LengthPrecision, SQLSMALLINT ParameterScale, SQLPOINTER ParameterValue, SQLLEN* StrLen_or_Ind)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLBindParam(StatementHandle, ParameterNumber, ValueType, ParameterType, LengthPrecision, ParameterScale, ParameterValue, StrLen_or_Ind);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLUSMALLINT(ParameterNumber);
	char* arg3 = formatSQLSMALLINT(ValueType);
	char* arg4 = formatSQLSMALLINT(ParameterType);
	char* arg5 = formatSQLULEN(LengthPrecision);
	char* arg6 = formatSQLSMALLINT(ParameterScale);
	char* arg7 = formatSQLPOINTER(ParameterValue);
	char* arg8 = formatPointer((void*)StrLen_or_Ind);
	log_odbc_call("SQLBindParam", ret, &tvStart, &tvEnd, 8, "SQLHSTMT", "StatementHandle", arg1, "SQLUSMALLINT", "ParameterNumber", arg2, "SQLSMALLINT", "ValueType", arg3, "SQLSMALLINT", "ParameterType", arg4, "SQLULEN", "LengthPrecision", arg5, "SQLSMALLINT", "ParameterScale", arg6, "SQLPOINTER", "ParameterValue", arg7, "SQLLEN*", "StrLen_or_Ind", arg8);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	return ret;
}

SQLRETURN SQL_API SQLCancel(SQLHSTMT StatementHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLCancel(StatementHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	log_odbc_call("SQLCancel", ret, &tvStart, &tvEnd, 1, "SQLHSTMT", "StatementHandle", arg1);
	delete [] arg1;
	return ret;
}

SQLRETURN SQL_API SQLCloseCursor(SQLHSTMT StatementHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLCloseCursor(StatementHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	log_odbc_call("SQLCloseCursor", ret, &tvStart, &tvEnd, 1, "SQLHSTMT", "StatementHandle", arg1);
	delete [] arg1;
	return ret;
}

SQLRETURN SQL_API SQLColAttribute(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLUSMALLINT FieldIdentifier, SQLPOINTER CharacterAttribute, SQLSMALLINT BufferLength, SQLSMALLINT* StringLength, SQLLEN* NumericAttribute)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLColAttribute(StatementHandle, ColumnNumber, FieldIdentifier, CharacterAttribute, BufferLength, StringLength, NumericAttribute);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLUSMALLINT(ColumnNumber);
	char* arg3 = formatSQLUSMALLINT(FieldIdentifier);
	char* arg4 = formatSQLPOINTER(CharacterAttribute);
	char* arg5 = formatSQLSMALLINT(BufferLength);
	char* arg6 = formatPointer((void*)StringLength);
	char* arg7 = formatPointer((void*)NumericAttribute);
	log_odbc_call("SQLColAttribute", ret, &tvStart, &tvEnd, 7, "SQLHSTMT", "StatementHandle", arg1, "SQLUSMALLINT", "ColumnNumber", arg2, "SQLUSMALLINT", "FieldIdentifier", arg3, "SQLPOINTER", "CharacterAttribute", arg4, "SQLSMALLINT", "BufferLength", arg5, "SQLSMALLINT*", "StringLength", arg6, "SQLLEN*", "NumericAttribute", arg7);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	return ret;
}

SQLRETURN SQL_API SQLColumns(SQLHSTMT StatementHandle, SQLCHAR* CatalogName, SQLSMALLINT NameLength1, SQLCHAR* SchemaName, SQLSMALLINT NameLength2, SQLCHAR* TableName, SQLSMALLINT NameLength3, SQLCHAR* ColumnName, SQLSMALLINT NameLength4)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLColumns(StatementHandle, CatalogName, NameLength1, SchemaName, NameLength2, TableName, NameLength3, ColumnName, NameLength4);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatPointer((void*)CatalogName);
	char* arg3 = formatSQLSMALLINT(NameLength1);
	char* arg4 = formatPointer((void*)SchemaName);
	char* arg5 = formatSQLSMALLINT(NameLength2);
	char* arg6 = formatPointer((void*)TableName);
	char* arg7 = formatSQLSMALLINT(NameLength3);
	char* arg8 = formatPointer((void*)ColumnName);
	char* arg9 = formatSQLSMALLINT(NameLength4);
	log_odbc_call("SQLColumns", ret, &tvStart, &tvEnd, 9, "SQLHSTMT", "StatementHandle", arg1, "SQLCHAR*", "CatalogName", arg2, "SQLSMALLINT", "NameLength1", arg3, "SQLCHAR*", "SchemaName", arg4, "SQLSMALLINT", "NameLength2", arg5, "SQLCHAR*", "TableName", arg6, "SQLSMALLINT", "NameLength3", arg7, "SQLCHAR*", "ColumnName", arg8, "SQLSMALLINT", "NameLength4", arg9);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	delete [] arg9;
	return ret;
}

SQLRETURN SQL_API SQLConnect(SQLHDBC ConnectionHandle, SQLCHAR* ServerName, SQLSMALLINT NameLength1, SQLCHAR* UserName, SQLSMALLINT NameLength2, SQLCHAR* Authentication, SQLSMALLINT NameLength3)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLConnect(ConnectionHandle, ServerName, NameLength1, UserName, NameLength2, Authentication, NameLength3);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDBC(ConnectionHandle);
	char* arg2 = formatSQLCHAR(ServerName);
	char* arg3 = formatSQLSMALLINT(NameLength1);
	char* arg4 = formatSQLCHAR(UserName);
	char* arg5 = formatSQLSMALLINT(NameLength2);
	char* arg6 = formatPointer((void*)Authentication);
	char* arg7 = formatSQLSMALLINT(NameLength3);
	log_odbc_call("SQLConnect", ret, &tvStart, &tvEnd, 7, "SQLHDBC", "ConnectionHandle", arg1, "SQLCHAR*", "ServerName", arg2, "SQLSMALLINT", "NameLength1", arg3, "SQLCHAR*", "UserName", arg4, "SQLSMALLINT", "NameLength2", arg5, "SQLCHAR*", "Authentication", arg6, "SQLSMALLINT", "NameLength3", arg7);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	return ret;
}

SQLRETURN SQL_API SQLDriverConnect( SQLHDBC            hdbc, SQLHWND            hwnd, SQLCHAR              *szConnStrIn, SQLSMALLINT        cbConnStrIn, SQLCHAR          *szConnStrOut, SQLSMALLINT        cbConnStrOutMax, SQLSMALLINT          *pcbConnStrOut, SQLUSMALLINT       fDriverCompletion)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLDriverConnect(hdbc, hwnd, szConnStrIn, cbConnStrIn, szConnStrOut, cbConnStrOutMax, pcbConnStrOut, fDriverCompletion);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDBC(hdbc);
	char* arg2 = formatSQLHWND(hwnd);
	char* arg3 = formatSQLCHAR(szConnStrIn);
	char* arg4 = formatSQLSMALLINT(cbConnStrIn);
	char* arg5 = formatPointer((void*)szConnStrOut);
	char* arg6 = formatSQLSMALLINT(cbConnStrOutMax);
	char* arg7 = formatPointer((void*)pcbConnStrOut);
	char* arg8 = formatSQLUSMALLINT(fDriverCompletion);
	log_odbc_call("SQLDriverConnect", ret, &tvStart, &tvEnd, 8, "SQLHDBC", "hdbc", arg1, "SQLHWND", "hwnd", arg2, "SQLCHAR*", "szConnStrIn", arg3, "SQLSMALLINT", "cbConnStrIn", arg4, "SQLCHAR*", "szConnStrOut", arg5, "SQLSMALLINT", "cbConnStrOutMax", arg6, "SQLSMALLINT*", "pcbConnStrOut", arg7, "SQLUSMALLINT", "fDriverCompletion", arg8);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	return ret;
}

SQLRETURN SQL_API SQLCopyDesc(SQLHDESC SourceDescHandle, SQLHDESC TargetDescHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLCopyDesc(SourceDescHandle, TargetDescHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDESC(SourceDescHandle);
	char* arg2 = formatSQLHDESC(TargetDescHandle);
	log_odbc_call("SQLCopyDesc", ret, &tvStart, &tvEnd, 2, "SQLHDESC", "SourceDescHandle", arg1, "SQLHDESC", "TargetDescHandle", arg2);
	delete [] arg1;
	delete [] arg2;
	return ret;
}

SQLRETURN SQL_API SQLDataSources(SQLHENV EnvironmentHandle, SQLUSMALLINT Direction, SQLCHAR* ServerName, SQLSMALLINT BufferLength1, SQLSMALLINT* NameLength1, SQLCHAR* Description, SQLSMALLINT BufferLength2, SQLSMALLINT* NameLength2)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLDataSources(EnvironmentHandle, Direction, ServerName, BufferLength1, NameLength1, Description, BufferLength2, NameLength2);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHENV(EnvironmentHandle);
	char* arg2 = formatSQLUSMALLINT(Direction);
	char* arg3 = formatPointer((void*)ServerName);
	char* arg4 = formatSQLSMALLINT(BufferLength1);
	char* arg5 = formatPointer((void*)NameLength1);
	char* arg6 = formatPointer((void*)Description);
	char* arg7 = formatSQLSMALLINT(BufferLength2);
	char* arg8 = formatPointer((void*)NameLength2);
	log_odbc_call("SQLDataSources", ret, &tvStart, &tvEnd, 8, "SQLHENV", "EnvironmentHandle", arg1, "SQLUSMALLINT", "Direction", arg2, "SQLCHAR*", "ServerName", arg3, "SQLSMALLINT", "BufferLength1", arg4, "SQLSMALLINT*", "NameLength1", arg5, "SQLCHAR*", "Description", arg6, "SQLSMALLINT", "BufferLength2", arg7, "SQLSMALLINT*", "NameLength2", arg8);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	return ret;
}

SQLRETURN SQL_API SQLDescribeCol(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLCHAR* ColumnName, SQLSMALLINT BufferLength, SQLSMALLINT* NameLength, SQLSMALLINT* DataType, SQLULEN* ColumnSize, SQLSMALLINT* DecimalDigits, SQLSMALLINT* Nullable)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLDescribeCol(StatementHandle, ColumnNumber, ColumnName, BufferLength, NameLength, DataType, ColumnSize, DecimalDigits, Nullable);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLUSMALLINT(ColumnNumber);
	char* arg3 = formatPointer((void*)ColumnName);
	char* arg4 = formatSQLSMALLINT(BufferLength);
	char* arg5 = formatPointer((void*)NameLength);
	char* arg6 = formatPointer((void*)DataType);
	char* arg7 = formatPointer((void*)ColumnSize);
	char* arg8 = formatPointer((void*)DecimalDigits);
	char* arg9 = formatPointer((void*)Nullable);
	log_odbc_call("SQLDescribeCol", ret, &tvStart, &tvEnd, 9, "SQLHSTMT", "StatementHandle", arg1, "SQLUSMALLINT", "ColumnNumber", arg2, "SQLCHAR*", "ColumnName", arg3, "SQLSMALLINT", "BufferLength", arg4, "SQLSMALLINT*", "NameLength", arg5, "SQLSMALLINT*", "DataType", arg6, "SQLULEN*", "ColumnSize", arg7, "SQLSMALLINT*", "DecimalDigits", arg8, "SQLSMALLINT*", "Nullable", arg9);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	delete [] arg9;
	return ret;
}

SQLRETURN SQL_API SQLDisconnect(SQLHDBC ConnectionHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLDisconnect(ConnectionHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDBC(ConnectionHandle);
	log_odbc_call("SQLDisconnect", ret, &tvStart, &tvEnd, 1, "SQLHDBC", "ConnectionHandle", arg1);
	delete [] arg1;
	return ret;
}

SQLRETURN SQL_API SQLEndTran(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT CompletionType)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLEndTran(HandleType, Handle, CompletionType);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLSMALLINT(HandleType);
	char* arg2 = formatSQLHANDLE(Handle);
	char* arg3 = formatSQLSMALLINT(CompletionType);
	log_odbc_call("SQLEndTran", ret, &tvStart, &tvEnd, 3, "SQLSMALLINT", "HandleType", arg1, "SQLHANDLE", "Handle", arg2, "SQLSMALLINT", "CompletionType", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLError(SQLHENV EnvironmentHandle, SQLHDBC ConnectionHandle, SQLHSTMT StatementHandle, SQLCHAR* Sqlstate, SQLINTEGER* NativeError, SQLCHAR* MessageText, SQLSMALLINT BufferLength, SQLSMALLINT* TextLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLError(EnvironmentHandle, ConnectionHandle, StatementHandle, Sqlstate, NativeError, MessageText, BufferLength, TextLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHENV(EnvironmentHandle);
	char* arg2 = formatSQLHDBC(ConnectionHandle);
	char* arg3 = formatSQLHSTMT(StatementHandle);
	char* arg4 = formatPointer((void*)Sqlstate);
	char* arg5 = formatPointer((void*)NativeError);
	char* arg6 = formatPointer((void*)MessageText);
	char* arg7 = formatSQLSMALLINT(BufferLength);
	char* arg8 = formatPointer((void*)TextLength);
	log_odbc_call("SQLError", ret, &tvStart, &tvEnd, 8, "SQLHENV", "EnvironmentHandle", arg1, "SQLHDBC", "ConnectionHandle", arg2, "SQLHSTMT", "StatementHandle", arg3, "SQLCHAR*", "Sqlstate", arg4, "SQLINTEGER*", "NativeError", arg5, "SQLCHAR*", "MessageText", arg6, "SQLSMALLINT", "BufferLength", arg7, "SQLSMALLINT*", "TextLength", arg8);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	return ret;
}

SQLRETURN SQL_API SQLExecDirect(SQLHSTMT StatementHandle, SQLCHAR* StatementText, SQLINTEGER TextLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLExecDirect(StatementHandle, StatementText, TextLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLCHAR(StatementText);
	char* arg3 = formatSQLINTEGER(TextLength);
	log_odbc_call("SQLExecDirect", ret, &tvStart, &tvEnd, 3, "SQLHSTMT", "StatementHandle", arg1, "SQLCHAR*", "StatementText", arg2, "SQLINTEGER", "TextLength", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLExecute(SQLHSTMT StatementHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLExecute(StatementHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	log_odbc_call("SQLExecute", ret, &tvStart, &tvEnd, 1, "SQLHSTMT", "StatementHandle", arg1);
	delete [] arg1;
	return ret;
}

SQLRETURN SQL_API SQLFetch(SQLHSTMT StatementHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLFetch(StatementHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	log_odbc_call("SQLFetch", ret, &tvStart, &tvEnd, 1, "SQLHSTMT", "StatementHandle", arg1);
	delete [] arg1;
	return ret;
}

SQLRETURN SQL_API SQLFetchScroll(SQLHSTMT StatementHandle, SQLSMALLINT FetchOrientation, SQLLEN FetchOffset)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLFetchScroll(StatementHandle, FetchOrientation, FetchOffset);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLSMALLINT(FetchOrientation);
	char* arg3 = formatSQLLEN(FetchOffset);
	log_odbc_call("SQLFetchScroll", ret, &tvStart, &tvEnd, 3, "SQLHSTMT", "StatementHandle", arg1, "SQLSMALLINT", "FetchOrientation", arg2, "SQLLEN", "FetchOffset", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLFreeConnect(SQLHDBC ConnectionHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLFreeConnect(ConnectionHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDBC(ConnectionHandle);
	log_odbc_call("SQLFreeConnect", ret, &tvStart, &tvEnd, 1, "SQLHDBC", "ConnectionHandle", arg1);
	delete [] arg1;
	return ret;
}

SQLRETURN SQL_API SQLFreeEnv(SQLHENV EnvironmentHandle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLFreeEnv(EnvironmentHandle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHENV(EnvironmentHandle);
	log_odbc_call("SQLFreeEnv", ret, &tvStart, &tvEnd, 1, "SQLHENV", "EnvironmentHandle", arg1);
	delete [] arg1;
	return ret;
}

SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT StatementHandle, SQLUSMALLINT Option)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLFreeStmt(StatementHandle, Option);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLUSMALLINT(Option);
	log_odbc_call("SQLFreeStmt", ret, &tvStart, &tvEnd, 2, "SQLHSTMT", "StatementHandle", arg1, "SQLUSMALLINT", "Option", arg2);
	delete [] arg1;
	delete [] arg2;
	return ret;
}

SQLRETURN SQL_API SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLFreeHandle(HandleType, Handle);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLSMALLINT(HandleType);
	char* arg2 = formatSQLHANDLE(Handle);
	log_odbc_call("SQLFreeHandle", ret, &tvStart, &tvEnd, 2, "SQLSMALLINT", "HandleType", arg1, "SQLHANDLE", "Handle", arg2);
	delete [] arg1;
	delete [] arg2;
	return ret;
}

SQLRETURN SQL_API SQLGetConnectAttr(SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER BufferLength, SQLINTEGER* StringLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetConnectAttr(ConnectionHandle, Attribute, Value, BufferLength, StringLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDBC(ConnectionHandle);
	char* arg2 = formatSQLINTEGER(Attribute);
	char* arg3 = formatSQLPOINTER(Value);
	char* arg4 = formatSQLINTEGER(BufferLength);
	char* arg5 = formatPointer((void*)StringLength);
	log_odbc_call("SQLGetConnectAttr", ret, &tvStart, &tvEnd, 5, "SQLHDBC", "ConnectionHandle", arg1, "SQLINTEGER", "Attribute", arg2, "SQLPOINTER", "Value", arg3, "SQLINTEGER", "BufferLength", arg4, "SQLINTEGER*", "StringLength", arg5);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	return ret;
}

SQLRETURN SQL_API SQLGetConnectOption(SQLHDBC ConnectionHandle, SQLUSMALLINT Option, SQLPOINTER Value)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetConnectOption(ConnectionHandle, Option, Value);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDBC(ConnectionHandle);
	char* arg2 = formatSQLUSMALLINT(Option);
	char* arg3 = formatSQLPOINTER(Value);
	log_odbc_call("SQLGetConnectOption", ret, &tvStart, &tvEnd, 3, "SQLHDBC", "ConnectionHandle", arg1, "SQLUSMALLINT", "Option", arg2, "SQLPOINTER", "Value", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLGetCursorName(SQLHSTMT StatementHandle, SQLCHAR* CursorName, SQLSMALLINT BufferLength, SQLSMALLINT* NameLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetCursorName(StatementHandle, CursorName, BufferLength, NameLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatPointer((void*)CursorName);
	char* arg3 = formatSQLSMALLINT(BufferLength);
	char* arg4 = formatPointer((void*)NameLength);
	log_odbc_call("SQLGetCursorName", ret, &tvStart, &tvEnd, 4, "SQLHSTMT", "StatementHandle", arg1, "SQLCHAR*", "CursorName", arg2, "SQLSMALLINT", "BufferLength", arg3, "SQLSMALLINT*", "NameLength", arg4);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	return ret;
}

SQLRETURN SQL_API SQLGetData(SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLPOINTER TargetValue, SQLLEN BufferLength, SQLLEN* StrLen_or_Ind)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetData(StatementHandle, ColumnNumber, TargetType, TargetValue, BufferLength, StrLen_or_Ind);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLUSMALLINT(ColumnNumber);
	char* arg3 = formatSQLSMALLINT(TargetType);
	char* arg4 = formatSQLPOINTER(TargetValue);
	char* arg5 = formatSQLLEN(BufferLength);
	char* arg6 = formatPointer((void*)StrLen_or_Ind);
	log_odbc_call("SQLGetData", ret, &tvStart, &tvEnd, 6, "SQLHSTMT", "StatementHandle", arg1, "SQLUSMALLINT", "ColumnNumber", arg2, "SQLSMALLINT", "TargetType", arg3, "SQLPOINTER", "TargetValue", arg4, "SQLLEN", "BufferLength", arg5, "SQLLEN*", "StrLen_or_Ind", arg6);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	return ret;
}

SQLRETURN SQL_API SQLGetDescField(SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier, SQLPOINTER Value, SQLINTEGER BufferLength, SQLINTEGER* StringLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetDescField(DescriptorHandle, RecNumber, FieldIdentifier, Value, BufferLength, StringLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDESC(DescriptorHandle);
	char* arg2 = formatSQLSMALLINT(RecNumber);
	char* arg3 = formatSQLSMALLINT(FieldIdentifier);
	char* arg4 = formatSQLPOINTER(Value);
	char* arg5 = formatSQLINTEGER(BufferLength);
	char* arg6 = formatPointer((void*)StringLength);
	log_odbc_call("SQLGetDescField", ret, &tvStart, &tvEnd, 6, "SQLHDESC", "DescriptorHandle", arg1, "SQLSMALLINT", "RecNumber", arg2, "SQLSMALLINT", "FieldIdentifier", arg3, "SQLPOINTER", "Value", arg4, "SQLINTEGER", "BufferLength", arg5, "SQLINTEGER*", "StringLength", arg6);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	return ret;
}

SQLRETURN SQL_API SQLGetDescRec(SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber, SQLCHAR* Name, SQLSMALLINT BufferLength, SQLSMALLINT* StringLength, SQLSMALLINT* Type, SQLSMALLINT* SubType, SQLLEN* Length, SQLSMALLINT* Precision, SQLSMALLINT* Scale, SQLSMALLINT* Nullable)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetDescRec(DescriptorHandle, RecNumber, Name, BufferLength, StringLength, Type, SubType, Length, Precision, Scale, Nullable);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDESC(DescriptorHandle);
	char* arg2 = formatSQLSMALLINT(RecNumber);
	char* arg3 = formatPointer((void*)Name);
	char* arg4 = formatSQLSMALLINT(BufferLength);
	char* arg5 = formatPointer((void*)StringLength);
	char* arg6 = formatPointer((void*)Type);
	char* arg7 = formatPointer((void*)SubType);
	char* arg8 = formatPointer((void*)Length);
	char* arg9 = formatPointer((void*)Precision);
	char* arg10 = formatPointer((void*)Scale);
	char* arg11 = formatPointer((void*)Nullable);
	log_odbc_call("SQLGetDescRec", ret, &tvStart, &tvEnd, 11, "SQLHDESC", "DescriptorHandle", arg1, "SQLSMALLINT", "RecNumber", arg2, "SQLCHAR*", "Name", arg3, "SQLSMALLINT", "BufferLength", arg4, "SQLSMALLINT*", "StringLength", arg5, "SQLSMALLINT*", "Type", arg6, "SQLSMALLINT*", "SubType", arg7, "SQLLEN*", "Length", arg8, "SQLSMALLINT*", "Precision", arg9, "SQLSMALLINT*", "Scale", arg10, "SQLSMALLINT*", "Nullable", arg11);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	delete [] arg9;
	delete [] arg10;
	delete [] arg11;
	return ret;
}

SQLRETURN SQL_API SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier, SQLPOINTER DiagInfo, SQLSMALLINT BufferLength, SQLSMALLINT* StringLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetDiagField(HandleType, Handle, RecNumber, DiagIdentifier, DiagInfo, BufferLength, StringLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLSMALLINT(HandleType);
	char* arg2 = formatSQLHANDLE(Handle);
	char* arg3 = formatSQLSMALLINT(RecNumber);
	char* arg4 = formatSQLSMALLINT(DiagIdentifier);
	char* arg5 = formatSQLPOINTER(DiagInfo);
	char* arg6 = formatSQLSMALLINT(BufferLength);
	char* arg7 = formatPointer((void*)StringLength);
	log_odbc_call("SQLGetDiagField", ret, &tvStart, &tvEnd, 7, "SQLSMALLINT", "HandleType", arg1, "SQLHANDLE", "Handle", arg2, "SQLSMALLINT", "RecNumber", arg3, "SQLSMALLINT", "DiagIdentifier", arg4, "SQLPOINTER", "DiagInfo", arg5, "SQLSMALLINT", "BufferLength", arg6, "SQLSMALLINT*", "StringLength", arg7);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	return ret;
}

SQLRETURN SQL_API SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle, SQLSMALLINT RecNumber, SQLCHAR* Sqlstate, SQLINTEGER* NativeError, SQLCHAR* MessageText, SQLSMALLINT BufferLength, SQLSMALLINT* TextLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetDiagRec(HandleType, Handle, RecNumber, Sqlstate, NativeError, MessageText, BufferLength, TextLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLSMALLINT(HandleType);
	char* arg2 = formatSQLHANDLE(Handle);
	char* arg3 = formatSQLSMALLINT(RecNumber);
	char* arg4 = formatPointer((void*)Sqlstate);
	char* arg5 = formatPointer((void*)NativeError);
	char* arg6 = formatPointer((void*)MessageText);
	char* arg7 = formatSQLSMALLINT(BufferLength);
	char* arg8 = formatPointer((void*)TextLength);
	log_odbc_call("SQLGetDiagRec", ret, &tvStart, &tvEnd, 8, "SQLSMALLINT", "HandleType", arg1, "SQLHANDLE", "Handle", arg2, "SQLSMALLINT", "RecNumber", arg3, "SQLCHAR*", "Sqlstate", arg4, "SQLINTEGER*", "NativeError", arg5, "SQLCHAR*", "MessageText", arg6, "SQLSMALLINT", "BufferLength", arg7, "SQLSMALLINT*", "TextLength", arg8);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	return ret;
}

SQLRETURN SQL_API SQLGetEnvAttr(SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER BufferLength, SQLINTEGER* StringLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetEnvAttr(EnvironmentHandle, Attribute, Value, BufferLength, StringLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHENV(EnvironmentHandle);
	char* arg2 = formatSQLINTEGER(Attribute);
	char* arg3 = formatSQLPOINTER(Value);
	char* arg4 = formatSQLINTEGER(BufferLength);
	char* arg5 = formatPointer((void*)StringLength);
	log_odbc_call("SQLGetEnvAttr", ret, &tvStart, &tvEnd, 5, "SQLHENV", "EnvironmentHandle", arg1, "SQLINTEGER", "Attribute", arg2, "SQLPOINTER", "Value", arg3, "SQLINTEGER", "BufferLength", arg4, "SQLINTEGER*", "StringLength", arg5);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	return ret;
}

SQLRETURN SQL_API SQLGetInfo(SQLHDBC ConnectionHandle, SQLUSMALLINT InfoType, SQLPOINTER InfoValue, SQLSMALLINT BufferLength, SQLSMALLINT* StringLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetInfo(ConnectionHandle, InfoType, InfoValue, BufferLength, StringLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDBC(ConnectionHandle);
	char* arg2 = formatSQLUSMALLINT(InfoType);
	char* arg3 = formatSQLPOINTER(InfoValue);
	char* arg4 = formatSQLSMALLINT(BufferLength);
	char* arg5 = formatPointer((void*)StringLength);
	log_odbc_call("SQLGetInfo", ret, &tvStart, &tvEnd, 5, "SQLHDBC", "ConnectionHandle", arg1, "SQLUSMALLINT", "InfoType", arg2, "SQLPOINTER", "InfoValue", arg3, "SQLSMALLINT", "BufferLength", arg4, "SQLSMALLINT*", "StringLength", arg5);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	return ret;
}

SQLRETURN SQL_API SQLGetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER BufferLength, SQLINTEGER* StringLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetStmtAttr(StatementHandle, Attribute, Value, BufferLength, StringLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLINTEGER(Attribute);
	char* arg3 = formatSQLPOINTER(Value);
	char* arg4 = formatSQLINTEGER(BufferLength);
	char* arg5 = formatPointer((void*)StringLength);
	log_odbc_call("SQLGetStmtAttr", ret, &tvStart, &tvEnd, 5, "SQLHSTMT", "StatementHandle", arg1, "SQLINTEGER", "Attribute", arg2, "SQLPOINTER", "Value", arg3, "SQLINTEGER", "BufferLength", arg4, "SQLINTEGER*", "StringLength", arg5);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	return ret;
}

SQLRETURN SQL_API SQLGetStmtOption(SQLHSTMT StatementHandle, SQLUSMALLINT Option, SQLPOINTER Value)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetStmtOption(StatementHandle, Option, Value);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLUSMALLINT(Option);
	char* arg3 = formatSQLPOINTER(Value);
	log_odbc_call("SQLGetStmtOption", ret, &tvStart, &tvEnd, 3, "SQLHSTMT", "StatementHandle", arg1, "SQLUSMALLINT", "Option", arg2, "SQLPOINTER", "Value", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLGetTypeInfo(SQLHSTMT StatementHandle, SQLSMALLINT DataType)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLGetTypeInfo(StatementHandle, DataType);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLSMALLINT(DataType);
	log_odbc_call("SQLGetTypeInfo", ret, &tvStart, &tvEnd, 2, "SQLHSTMT", "StatementHandle", arg1, "SQLSMALLINT", "DataType", arg2);
	delete [] arg1;
	delete [] arg2;
	return ret;
}

SQLRETURN SQL_API SQLNumResultCols(SQLHSTMT StatementHandle, SQLSMALLINT* ColumnCount)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLNumResultCols(StatementHandle, ColumnCount);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatPointer((void*)ColumnCount);
	log_odbc_call("SQLNumResultCols", ret, &tvStart, &tvEnd, 2, "SQLHSTMT", "StatementHandle", arg1, "SQLSMALLINT*", "ColumnCount", arg2);
	delete [] arg1;
	delete [] arg2;
	return ret;
}

SQLRETURN SQL_API SQLParamData(SQLHSTMT StatementHandle, SQLPOINTER* Value)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLParamData(StatementHandle, Value);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatPointer((void*)Value);
	log_odbc_call("SQLParamData", ret, &tvStart, &tvEnd, 2, "SQLHSTMT", "StatementHandle", arg1, "SQLPOINTER*", "Value", arg2);
	delete [] arg1;
	delete [] arg2;
	return ret;
}

SQLRETURN SQL_API SQLPrepare(SQLHSTMT StatementHandle, SQLCHAR* StatementText, SQLINTEGER TextLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLPrepare(StatementHandle, StatementText, TextLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatPointer((void*)StatementText);
	char* arg3 = formatSQLINTEGER(TextLength);
	log_odbc_call("SQLPrepare", ret, &tvStart, &tvEnd, 3, "SQLHSTMT", "StatementHandle", arg1, "SQLCHAR*", "StatementText", arg2, "SQLINTEGER", "TextLength", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLPutData(SQLHSTMT StatementHandle, SQLPOINTER Data, SQLLEN StrLen_or_Ind)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLPutData(StatementHandle, Data, StrLen_or_Ind);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLPOINTER(Data);
	char* arg3 = formatSQLLEN(StrLen_or_Ind);
	log_odbc_call("SQLPutData", ret, &tvStart, &tvEnd, 3, "SQLHSTMT", "StatementHandle", arg1, "SQLPOINTER", "Data", arg2, "SQLLEN", "StrLen_or_Ind", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLRowCount(SQLHSTMT StatementHandle, SQLLEN* RowCount)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLRowCount(StatementHandle, RowCount);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatPointer((void*)RowCount);
	log_odbc_call("SQLRowCount", ret, &tvStart, &tvEnd, 2, "SQLHSTMT", "StatementHandle", arg1, "SQLLEN*", "RowCount", arg2);
	delete [] arg1;
	delete [] arg2;
	return ret;
}

SQLRETURN SQL_API SQLSetConnectAttr(SQLHDBC ConnectionHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLSetConnectAttr(ConnectionHandle, Attribute, Value, StringLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDBC(ConnectionHandle);
	char* arg2 = formatSQLINTEGER(Attribute);
	char* arg3 = formatSQLPOINTER(Value);
	char* arg4 = formatSQLINTEGER(StringLength);
	log_odbc_call("SQLSetConnectAttr", ret, &tvStart, &tvEnd, 4, "SQLHDBC", "ConnectionHandle", arg1, "SQLINTEGER", "Attribute", arg2, "SQLPOINTER", "Value", arg3, "SQLINTEGER", "StringLength", arg4);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	return ret;
}

SQLRETURN SQL_API SQLSetConnectOption(SQLHDBC ConnectionHandle, SQLUSMALLINT Option, SQLULEN Value)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLSetConnectOption(ConnectionHandle, Option, Value);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDBC(ConnectionHandle);
	char* arg2 = formatSQLUSMALLINT(Option);
	char* arg3 = formatSQLULEN(Value);
	log_odbc_call("SQLSetConnectOption", ret, &tvStart, &tvEnd, 3, "SQLHDBC", "ConnectionHandle", arg1, "SQLUSMALLINT", "Option", arg2, "SQLULEN", "Value", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLSetCursorName(SQLHSTMT StatementHandle, SQLCHAR* CursorName, SQLSMALLINT NameLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLSetCursorName(StatementHandle, CursorName, NameLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatPointer((void*)CursorName);
	char* arg3 = formatSQLSMALLINT(NameLength);
	log_odbc_call("SQLSetCursorName", ret, &tvStart, &tvEnd, 3, "SQLHSTMT", "StatementHandle", arg1, "SQLCHAR*", "CursorName", arg2, "SQLSMALLINT", "NameLength", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLSetDescField(SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier, SQLPOINTER Value, SQLINTEGER BufferLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLSetDescField(DescriptorHandle, RecNumber, FieldIdentifier, Value, BufferLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDESC(DescriptorHandle);
	char* arg2 = formatSQLSMALLINT(RecNumber);
	char* arg3 = formatSQLSMALLINT(FieldIdentifier);
	char* arg4 = formatSQLPOINTER(Value);
	char* arg5 = formatSQLINTEGER(BufferLength);
	log_odbc_call("SQLSetDescField", ret, &tvStart, &tvEnd, 5, "SQLHDESC", "DescriptorHandle", arg1, "SQLSMALLINT", "RecNumber", arg2, "SQLSMALLINT", "FieldIdentifier", arg3, "SQLPOINTER", "Value", arg4, "SQLINTEGER", "BufferLength", arg5);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	return ret;
}

SQLRETURN SQL_API SQLSetDescRec(SQLHDESC DescriptorHandle, SQLSMALLINT RecNumber, SQLSMALLINT Type, SQLSMALLINT SubType, SQLLEN Length, SQLSMALLINT Precision, SQLSMALLINT Scale, SQLPOINTER Data, SQLLEN* StringLength, SQLLEN* Indicator)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLSetDescRec(DescriptorHandle, RecNumber, Type, SubType, Length, Precision, Scale, Data, StringLength, Indicator);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHDESC(DescriptorHandle);
	char* arg2 = formatSQLSMALLINT(RecNumber);
	char* arg3 = formatSQLSMALLINT(Type);
	char* arg4 = formatSQLSMALLINT(SubType);
	char* arg5 = formatSQLLEN(Length);
	char* arg6 = formatSQLSMALLINT(Precision);
	char* arg7 = formatSQLSMALLINT(Scale);
	char* arg8 = formatSQLPOINTER(Data);
	char* arg9 = formatPointer((void*)StringLength);
	char* arg10 = formatPointer((void*)Indicator);
	log_odbc_call("SQLSetDescRec", ret, &tvStart, &tvEnd, 10, "SQLHDESC", "DescriptorHandle", arg1, "SQLSMALLINT", "RecNumber", arg2, "SQLSMALLINT", "Type", arg3, "SQLSMALLINT", "SubType", arg4, "SQLLEN", "Length", arg5, "SQLSMALLINT", "Precision", arg6, "SQLSMALLINT", "Scale", arg7, "SQLPOINTER", "Data", arg8, "SQLLEN*", "StringLength", arg9, "SQLLEN*", "Indicator", arg10);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	delete [] arg9;
	delete [] arg10;
	return ret;
}

SQLRETURN SQL_API SQLSetEnvAttr(SQLHENV EnvironmentHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLSetEnvAttr(EnvironmentHandle, Attribute, Value, StringLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHENV(EnvironmentHandle);
	char* arg2 = formatSQLINTEGER(Attribute);
	char* arg3 = formatSQLPOINTER(Value);
	char* arg4 = formatSQLINTEGER(StringLength);
	log_odbc_call("SQLSetEnvAttr", ret, &tvStart, &tvEnd, 4, "SQLHENV", "EnvironmentHandle", arg1, "SQLINTEGER", "Attribute", arg2, "SQLPOINTER", "Value", arg3, "SQLINTEGER", "StringLength", arg4);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	return ret;
}

SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle, SQLINTEGER Attribute, SQLPOINTER Value, SQLINTEGER StringLength)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLSetStmtAttr(StatementHandle, Attribute, Value, StringLength);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLINTEGER(Attribute);
	char* arg3 = formatSQLPOINTER(Value);
	char* arg4 = formatSQLINTEGER(StringLength);
	log_odbc_call("SQLSetStmtAttr", ret, &tvStart, &tvEnd, 4, "SQLHSTMT", "StatementHandle", arg1, "SQLINTEGER", "Attribute", arg2, "SQLPOINTER", "Value", arg3, "SQLINTEGER", "StringLength", arg4);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	return ret;
}

SQLRETURN SQL_API SQLSetStmtOption(SQLHSTMT StatementHandle, SQLUSMALLINT Option, SQLULEN Value)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLSetStmtOption(StatementHandle, Option, Value);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLUSMALLINT(Option);
	char* arg3 = formatSQLULEN(Value);
	log_odbc_call("SQLSetStmtOption", ret, &tvStart, &tvEnd, 3, "SQLHSTMT", "StatementHandle", arg1, "SQLUSMALLINT", "Option", arg2, "SQLULEN", "Value", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLSpecialColumns(SQLHSTMT StatementHandle, SQLUSMALLINT IdentifierType, SQLCHAR* CatalogName, SQLSMALLINT NameLength1, SQLCHAR* SchemaName, SQLSMALLINT NameLength2, SQLCHAR* TableName, SQLSMALLINT NameLength3, SQLUSMALLINT Scope, SQLUSMALLINT Nullable)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLSpecialColumns(StatementHandle, IdentifierType, CatalogName, NameLength1, SchemaName, NameLength2, TableName, NameLength3, Scope, Nullable);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLUSMALLINT(IdentifierType);
	char* arg3 = formatPointer((void*)CatalogName);
	char* arg4 = formatSQLSMALLINT(NameLength1);
	char* arg5 = formatPointer((void*)SchemaName);
	char* arg6 = formatSQLSMALLINT(NameLength2);
	char* arg7 = formatPointer((void*)TableName);
	char* arg8 = formatSQLSMALLINT(NameLength3);
	char* arg9 = formatSQLUSMALLINT(Scope);
	char* arg10 = formatSQLUSMALLINT(Nullable);
	log_odbc_call("SQLSpecialColumns", ret, &tvStart, &tvEnd, 10, "SQLHSTMT", "StatementHandle", arg1, "SQLUSMALLINT", "IdentifierType", arg2, "SQLCHAR*", "CatalogName", arg3, "SQLSMALLINT", "NameLength1", arg4, "SQLCHAR*", "SchemaName", arg5, "SQLSMALLINT", "NameLength2", arg6, "SQLCHAR*", "TableName", arg7, "SQLSMALLINT", "NameLength3", arg8, "SQLUSMALLINT", "Scope", arg9, "SQLUSMALLINT", "Nullable", arg10);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	delete [] arg9;
	delete [] arg10;
	return ret;
}

SQLRETURN SQL_API SQLStatistics(SQLHSTMT StatementHandle, SQLCHAR* CatalogName, SQLSMALLINT NameLength1, SQLCHAR* SchemaName, SQLSMALLINT NameLength2, SQLCHAR* TableName, SQLSMALLINT NameLength3, SQLUSMALLINT Unique, SQLUSMALLINT Reserved)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLStatistics(StatementHandle, CatalogName, NameLength1, SchemaName, NameLength2, TableName, NameLength3, Unique, Reserved);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatPointer((void*)CatalogName);
	char* arg3 = formatSQLSMALLINT(NameLength1);
	char* arg4 = formatPointer((void*)SchemaName);
	char* arg5 = formatSQLSMALLINT(NameLength2);
	char* arg6 = formatPointer((void*)TableName);
	char* arg7 = formatSQLSMALLINT(NameLength3);
	char* arg8 = formatSQLUSMALLINT(Unique);
	char* arg9 = formatSQLUSMALLINT(Reserved);
	log_odbc_call("SQLStatistics", ret, &tvStart, &tvEnd, 9, "SQLHSTMT", "StatementHandle", arg1, "SQLCHAR*", "CatalogName", arg2, "SQLSMALLINT", "NameLength1", arg3, "SQLCHAR*", "SchemaName", arg4, "SQLSMALLINT", "NameLength2", arg5, "SQLCHAR*", "TableName", arg6, "SQLSMALLINT", "NameLength3", arg7, "SQLUSMALLINT", "Unique", arg8, "SQLUSMALLINT", "Reserved", arg9);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	delete [] arg9;
	return ret;
}

SQLRETURN SQL_API SQLTables(SQLHSTMT StatementHandle, SQLCHAR* CatalogName, SQLSMALLINT NameLength1, SQLCHAR* SchemaName, SQLSMALLINT NameLength2, SQLCHAR* TableName, SQLSMALLINT NameLength3, SQLCHAR* TableType, SQLSMALLINT NameLength4)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLTables(StatementHandle, CatalogName, NameLength1, SchemaName, NameLength2, TableName, NameLength3, TableType, NameLength4);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatPointer((void*)CatalogName);
	char* arg3 = formatSQLSMALLINT(NameLength1);
	char* arg4 = formatPointer((void*)SchemaName);
	char* arg5 = formatSQLSMALLINT(NameLength2);
	char* arg6 = formatPointer((void*)TableName);
	char* arg7 = formatSQLSMALLINT(NameLength3);
	char* arg8 = formatPointer((void*)TableType);
	char* arg9 = formatSQLSMALLINT(NameLength4);
	log_odbc_call("SQLTables", ret, &tvStart, &tvEnd, 9, "SQLHSTMT", "StatementHandle", arg1, "SQLCHAR*", "CatalogName", arg2, "SQLSMALLINT", "NameLength1", arg3, "SQLCHAR*", "SchemaName", arg4, "SQLSMALLINT", "NameLength2", arg5, "SQLCHAR*", "TableName", arg6, "SQLSMALLINT", "NameLength3", arg7, "SQLCHAR*", "TableType", arg8, "SQLSMALLINT", "NameLength4", arg9);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	delete [] arg9;
	return ret;
}

SQLRETURN SQL_API SQLTransact(SQLHENV EnvironmentHandle, SQLHDBC ConnectionHandle, SQLUSMALLINT CompletionType)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLTransact(EnvironmentHandle, ConnectionHandle, CompletionType);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHENV(EnvironmentHandle);
	char* arg2 = formatSQLHDBC(ConnectionHandle);
	char* arg3 = formatSQLUSMALLINT(CompletionType);
	log_odbc_call("SQLTransact", ret, &tvStart, &tvEnd, 3, "SQLHENV", "EnvironmentHandle", arg1, "SQLHDBC", "ConnectionHandle", arg2, "SQLUSMALLINT", "CompletionType", arg3);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	return ret;
}

SQLRETURN SQL_API SQLSetParam(SQLHSTMT StatementHandle, SQLUSMALLINT ParameterNumber, SQLSMALLINT ValueType, SQLSMALLINT ParameterType, SQLULEN LengthPrecision, SQLSMALLINT ParameterScale, SQLPOINTER ParameterValue, SQLLEN* StrLen_or_Ind)  {
	struct timeval tvStart, tvEnd;
	gettimeofday(&tvStart, NULL);
	SQLRETURN ret = getWrapper()==NULL ? SQL_ERROR : getWrapper()->SQLSetParam(StatementHandle, ParameterNumber, ValueType, ParameterType, LengthPrecision, ParameterScale, ParameterValue, StrLen_or_Ind);
	gettimeofday(&tvEnd, NULL);
	char* arg1 = formatSQLHSTMT(StatementHandle);
	char* arg2 = formatSQLUSMALLINT(ParameterNumber);
	char* arg3 = formatSQLSMALLINT(ValueType);
	char* arg4 = formatSQLSMALLINT(ParameterType);
	char* arg5 = formatSQLULEN(LengthPrecision);
	char* arg6 = formatSQLSMALLINT(ParameterScale);
	char* arg7 = formatSQLPOINTER(ParameterValue);
	char* arg8 = formatPointer((void*)StrLen_or_Ind);
	log_odbc_call("SQLSetParam", ret, &tvStart, &tvEnd, 8, "SQLHSTMT", "StatementHandle", arg1, "SQLUSMALLINT", "ParameterNumber", arg2, "SQLSMALLINT", "ValueType", arg3, "SQLSMALLINT", "ParameterType", arg4, "SQLULEN", "LengthPrecision", arg5, "SQLSMALLINT", "ParameterScale", arg6, "SQLPOINTER", "ParameterValue", arg7, "SQLLEN*", "StrLen_or_Ind", arg8);
	delete [] arg1;
	delete [] arg2;
	delete [] arg3;
	delete [] arg4;
	delete [] arg5;
	delete [] arg6;
	delete [] arg7;
	delete [] arg8;
	return ret;
}

